using System;
using System.Collections.Generic;
using System.Text;

namespace DeflateLib
{
    /// <summary>
    /// Simple compressor implementation. Compresses sequences of 
    /// same bytes or pair of bytes.
    /// </summary>
    class CharSequenceCompressor : ICompressor
    {
        public void Initialize(byte[] data, int index, int length)
        {
            // do nothing
        }

        public CompressedData Compress(byte[] data, int index, int length)
        {
            CompressedData compressedData = new CompressedData();
            compressedData.WriteByte(data[0]);
            int i = 1;
            while (i < length - 2)
            {
                if (data[i - 1] == data[i + 1] && data[i] == data[i + 2])
                {
                    if (data[i] == data[i + 1])
                    {
                        int repeatLength = 3;
                        while (i + repeatLength < length &&
                            data[i] == data[i + repeatLength] &&
                            repeatLength < DeflateUtils.MaxLength) repeatLength++;
                        compressedData.WriteDistanceLength(1, repeatLength);
                        i += repeatLength;
                    }
                    else if (i < length - 3 && data[i + 1] == data[i + 3])
                    {
                        int repeatLength = 3;
                        compressedData.WriteByte(data[i++]);
                        while (i + repeatLength < length &&
                            data[i + (repeatLength & 1)] == data[i + repeatLength] &&
                            repeatLength < DeflateUtils.MaxLength) repeatLength++;
                        compressedData.WriteDistanceLength(2, repeatLength);
                        i += repeatLength;
                    }
                    else
                        compressedData.WriteByte(data[i++]);
                }
                else
                    compressedData.WriteByte(data[i++]);                
            }
            while (i < length)
            {
                compressedData.WriteByte(data[i++]);
            }
            return compressedData;
        }
    }

    /// <summary>
    /// A class factory for <see cref="CharSequenceCompressor"/>.
    /// </summary>
    class CharSequenceCompressorFactory : CompressorFactory
    {
        public override ICompressor CreateCompressor()
        {
            return new CharSequenceCompressor();
        }
    }
}
